//
//  HttpClient.m
//  LineByLine
//
//  Created by 병철 김 on 11. 10. 18..
//  Copyright (c) 2011 __MyCompanyName__. All rights reserved.
//

#import "HttpRequest.h"
#import "CommonUtil.h"
#import "QHTTPOperation.h"
#import "NetworkManager.h"


#define kArbitraryCapacity 10
#define kRequestTimeout 5
#define kMethodPost @"post"

@interface HttpRequest(Private)
- (NSString*) cookiesString;
- (NSString*) getParamsString;
- (void) setPostParam:(NSMutableURLRequest*) urlRequest;
- (void) setGetParam:(NSMutableURLRequest*) urlRequest;
- (NSMutableURLRequest*) newHttpRequest;
@end

@implementation HttpRequest 
@synthesize requestId, url, method, params, headers, cookies, responseData;


- (void) execute {
    NSURLRequest *request = [self newHttpRequest];
    httpOperation = [[QHTTPOperation alloc] initWithRequest:request];
    if (outputStream) {
        [httpOperation setResponseOutputStream:outputStream];
    }
    [[NetworkManager sharedManager] addNetworkManagementOperation:httpOperation finishedTarget:self action:@selector(didFinishRequest:)];
    [request release];
}

- (void) executeUrl:(NSString*) _url method:(NSString*) _method params:(NSString*)param, ... {
    [self setUrl:_url];
    [self setMethod:_method];
    
    va_list args;
	va_start(args, param);
    if (params == nil) {
        params = [[NSMutableDictionary alloc] initWithCapacity:kArbitraryCapacity];
    } else {
        [params removeAllObjects];
    }
    [CommonUtil setKeyValuesTo:params first:param valist:args];
    va_end(args);
    
    [self setHeaders:nil];
    [self setCookies:nil];
    
    [self execute];
}

- (void) setParamsKeyValue:(NSString*) param, ... {
    va_list args;
	va_start(args, param);
    if (params == nil) {
        params = [[NSMutableDictionary alloc] initWithCapacity:kArbitraryCapacity];
    } else {
        [params removeAllObjects];
    }
    [CommonUtil setKeyValuesTo:params first:param valist:args];
    va_end(args);
}

- (void) setHeadersKeyValue:(NSString*) header, ... {
    va_list args;
	va_start(args, header);
    if (headers == nil) {
        headers = [[NSMutableDictionary alloc] initWithCapacity:kArbitraryCapacity];
    } else {
        [headers removeAllObjects];
    }
    [CommonUtil setKeyValuesTo:headers first:header valist:args];
    va_end(args);
}

- (void) setCookiesKeyValue:(NSString*) cookie, ... {
    va_list args;
	va_start(args, cookie);
    if (cookies == nil) {
        cookies = [[NSMutableDictionary alloc] initWithCapacity:kArbitraryCapacity];
    } else {
        [cookies removeAllObjects];
    }
    [CommonUtil setKeyValuesTo:cookies first:cookie valist:args];
    va_end(args);
}


- (NSString*) cookiesString {
    if (cookies == nil) {
        return nil;
    }
    
    NSMutableString *cookiesString = [[NSMutableString alloc] init];
    for (NSString *key in cookies) {
        [cookiesString appendFormat:@"%@=%@;", key, [cookies valueForKey:key]];
    }
    
    return [cookiesString autorelease];
}

- (NSString*) getParamsString {
    if (params == nil) {
        return nil;
    }
    
    NSMutableString *paramString = [[NSMutableString alloc] init];
    for (NSString *key in params) {
        if ([paramString length] > 0) {
            [paramString appendString:@"&"];
        }
        NSString *value = [params valueForKey:key];
        [paramString appendFormat:@"%@=%@", key, [CommonUtil urlEncodeString:value usingEncoding:NSUTF8StringEncoding]];
    }
    
    return [paramString autorelease];
}

- (void) setPostParam:(NSMutableURLRequest*) urlRequest {
    NSString *paramString = [self getParamsString];
    [urlRequest setHTTPBody:[paramString dataUsingEncoding:NSUTF8StringEncoding]];
}

- (void) setGetParam:(NSMutableURLRequest*) urlRequest {
    NSString *paramString = [self getParamsString];
    NSString *requestUrl;
    
    if ([url rangeOfString:@"?"].location == NSNotFound) {
        requestUrl = [NSString stringWithFormat:@"%@?%@", url, paramString];
    } else {
        requestUrl = [NSString stringWithFormat:@"%@&%@", url, paramString];
    }
    
    [urlRequest setURL:[NSURL URLWithString:requestUrl]];
}

- (NSMutableURLRequest*) newHttpRequest {
    NSMutableURLRequest *urlRequest = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:kRequestTimeout];
    [urlRequest setHTTPMethod:method];
    [urlRequest setAllHTTPHeaderFields:headers];
    [urlRequest setValue:[self cookiesString] forHTTPHeaderField:@"Cookie"];
    
    if ([kMethodPost isEqualToString:method]) {
        [self setPostParam:urlRequest];
    } else {
        [self setGetParam:urlRequest];
    }
    return urlRequest;
}

- (void) setFinishTarget:(id) _finishTarget action:(SEL) _finishAction {
    finishTarget = _finishTarget;
    finishAction = _finishAction;
}

- (void) didFinishRequest:(QHTTPOperation*) httpOperation {
    [finishTarget performSelector:finishAction withObject:self];
}

- (void) close {
    if (httpOperation == nil) {
        return;
    }
    if (![httpOperation isFinished]) {
        NSLog(@"canceled");
        [httpOperation cancel];
    }
    [httpOperation release];
    httpOperation = nil;
}

- (NSData *)responseData {
    assert(httpOperation != nil);
    return [httpOperation responseBody];
}

- (NSOutputStream*) outputStream {
    assert(httpOperation != nil);
    return [httpOperation responseOutputStream];
}

- (void) setOutputStream:(NSOutputStream*) _outputStream {
    outputStream = _outputStream;
}

- (void)dealloc {
    if (httpOperation != nil) {
        [self close];
    }
    
    [url release];
    [method release];
    [params release];
    [headers release];
    [cookies release];
    [super dealloc];
}
@end
